<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CangjieMagic问答助手</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/jquery-jsonview/1.2.3/jquery.jsonview.css">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery-jsonview/1.2.3/jquery.jsonview.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dompurify@2.3.3/dist/purify.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/json.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/sql.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/java.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/python.min.js"></script>
    <style>
        .json-viewer {
            font-family: monospace;
            font-size: 14px;
            line-height: 1.5;
            color: #333;
            background-color: #f8f9fa;
            border-radius: 0.375rem;
            padding: 0.75rem;
            margin: 0.5rem 0;
            max-height: 400px;
            overflow-y: auto;
        }

        .json-viewer .key {
            color: #d63384;
        }

        .json-viewer .string {
            color: #20c997;
        }

        .json-viewer .number {
            color: #fd7e14;
        }

        .json-viewer .boolean {
            color: #6610f2;
        }

        .json-viewer .null {
            color: #6c757d;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        th, td {
            border: 1px solid #ddd;
            padding: 8px;
        }

        th {
            background-color: #f2f2f2;
        }
    </style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="max-w-4xl mx-auto p-4">
    <h1 class="text-2xl font-bold text-center text-gray-800 mb-6">CangjieMagic问答助手</h1>
    <div id="chat-window" class="bg-white rounded-lg shadow-md h-[600px] overflow-y-auto p-4 mb-4">
        <div class="flex items-start mb-4">
            <div class="bg-blue-500 text-white p-2 rounded-full mr-3">🤵🏻</div>
            <div class="bg-blue-100 rounded-lg p-3 max-w-[80%]">
                您好！我是CangjieMagic助手，有什么可以帮助您的吗？
            </div>
        </div>
    </div>
    <div class="flex">
        <input
                type="text"
                id="user-input"
                class="flex-1 px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
                placeholder="请输入您的回复..."
        >
        <button
                id="send-btn"
                class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-r-lg transition-colors"
        >
            发送
        </button>
    </div>
</div>

<script>
    let currentState = null;
    const chatWindow = document.getElementById('chat-window');
    const userInput = document.getElementById('user-input');
    const sendBtn = document.getElementById('send-btn');

    // ====== 修改点 1: 配置 marked 使用 highlight.js 进行代码高亮，并设置默认语言为 JavaScript ======
    marked.setOptions({
        highlight: function (code, lang) {
            // 确定要使用的语言
            let languageToUse = lang;

            // 如果没有指定语言，或者指定的语言不被 hljs 支持，则默认使用 javascript
            if (!languageToUse || !hljs.getLanguage(languageToUse)) {
                languageToUse = 'javascript';
            }

            // 使用确定的语言进行高亮
            try {
                return hljs.highlight(code, {language: languageToUse}).value;
            } catch (err) {
                // 如果高亮失败（比如代码有语法错误），返回原始代码
                // DOMPurify 会处理转义
                return code;
            }
        },
        langPrefix: 'hljs language-', // 设置 CSS 类名前缀，以匹配 highlight.js 的样式
        breaks: true // 支持换行符转 <br>
    });

    // ====== 修改点 2: 简化 addMessage 函数，让它只负责渲染 ======
    function addMessage(sender, content) {
        const messageDiv = document.createElement('div');
        messageDiv.className = `flex items-start mb-4 ${sender === 'user' ? 'justify-end' : ''}`;

        const avatar = document.createElement('div');
        avatar.className = `p-2 rounded-full mr-3 ${sender === 'user' ? 'bg-gray-300' : 'bg-blue-500 text-white'}`;
        avatar.textContent = sender === 'user' ? '👤' : '🤵🏻';

        const bubble = document.createElement('div');
        bubble.className = `rounded-lg p-3 max-w-[90%] whitespace-pre-wrap ${ // 添加 whitespace-pre-wrap 保留空格和换行
            sender === 'user' ? 'bg-gray-200' : 'bg-blue-100'
        }`;

        // 使用 marked 解析所有 Markdown 内容（包括代码块、列表等）
        // 然后用 DOMPurify 清理，防止 XSS 攻击
        bubble.innerHTML = DOMPurify.sanitize(marked.parse(content));

        messageDiv.appendChild(sender === 'user' ? bubble : avatar);
        messageDiv.appendChild(sender === 'user' ? avatar : bubble);
        chatWindow.appendChild(messageDiv);
        chatWindow.scrollTop = chatWindow.scrollHeight;
    }

    // 简单UUID生成函数
    function uuidv4() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            const r = Math.random() * 16 | 0;
            const v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    let sessionId = localStorage.getItem('sessionId') || uuidv4();
    localStorage.setItem('sessionId', sessionId);

    // 发送消息并建立SSE连接
    async function sendMessage() {
        const message = userInput.value.trim();
        if (!message) return;

        addMessage('user', message);
        userInput.value = '';

        try {
            await connectSSE(sessionId, message);
        } catch (error) {
            console.error('SSE连接错误:', error);
            addMessage('bot', '抱歉，连接服务器时出现问题');
        }
    }

    // ====== 修改点 3: 优化 SSE 连接处理，累积流式数据 ======
    async function connectSSE(sessionId, userInput) {
        const params = new URLSearchParams();
        params.append('sessionId', sessionId);
        params.append('q', userInput);
        //docker容器运行访问的端口
        const response = await fetch("http://localhost:8085/chat" + '?' + params.toString());
        //本地运行访问的端口
        //const response = await fetch("http://localhost:18881/chat" + '?' + params.toString());
        if (!response.ok || !response.body) {
            throw new Error(`HTTP错误! 状态: ${response.status}`);
        }
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';
        try {
            while (true) {
                const {done, value} = await reader.read();
                if (done) break;
                buffer += decoder.decode(value, {stream: true});
            }
             const re = /data:\s*([\s\S]*?)\ndata:\s*done/g;
             const all = [...buffer.matchAll(re)].map(m => m[1]);
             addMessage('bot', all.join('\n'));
        } finally {
            reader.cancel().catch(() => {
            });
        }
    }

    // 绑定事件
    sendBtn.addEventListener('click', sendMessage);
    userInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') sendMessage();
    });

    // 初始化对话
    window.onload = () => {
        // 首次请求触发工作流启动
        sendMessage();
    };
</script>


</body>
</html>